#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <numeric>
#include <chrono>
#include <thread>
#include "libserialport.h"
using namespace std;
static void print_sp_error(enum sp_return r) {
    if (r == SP_ERR_FAIL) {
        const char *msg = sp_last_error_message();
        std::cerr << "libserialport: SP_ERR_FAIL: " << (msg ? msg : "(no message)") << "\n";
    } else {
        std::cerr << "libserialport: error code " << r << "\n";
    }
}

bool configure_port(struct sp_port *port) {
    // 设置常用参数：115200 8N1 无流控
    if (sp_set_baudrate(port, 115200) != SP_OK) {
        print_sp_error(SP_ERR_FAIL);
        return false;
    }

    if (sp_set_bits(port, 8) != SP_OK) {
        print_sp_error(SP_ERR_FAIL); return false;
    }
    if (sp_set_parity(port, SP_PARITY_NONE) != SP_OK) {
        print_sp_error(SP_ERR_FAIL);
        return false;
    }
    if (sp_set_stopbits(port, 1) != SP_OK) {
        print_sp_error(SP_ERR_FAIL);
        return false;
    }
    if (sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE) != SP_OK) {
        print_sp_error(SP_ERR_FAIL);
        return false;
    }
    return true;
}

int run_half_duplex(struct sp_port *port) {
    std::string line;
    std::vector<char> rxbuf(1024);

    std::cout << "半双工模式 (阻塞)：输入文本回车发送。Ctrl+D/Ctrl+Z 退出。\n";
    while (true) {
        if (!std::getline(std::cin, line)) {
            std::cout << "stdin closed. exiting.\n";
            break;
        }

        // 发送（阻塞写，超时 1000ms）
        size_t to_write = line.size();
        const char *p = line.c_str();
        int written = sp_blocking_write(port, p, to_write, 1000 /*ms*/);
        if (written < 0) {
            print_sp_error((enum sp_return)written);
            // 继续或退出视情况决定，这里继续
        } else {
            std::cout << "[-> TX " << written << " bytes]\n";
        }

        // 发送换行（可选，视协议）
        const char *nl = "\r\n";
        sp_blocking_write(port, nl, 2, 200);

        // 接收（阻塞读，等待最多 2000ms）
        int r = sp_blocking_read(port, rxbuf.data(), (int)rxbuf.size()-1, 2000 /*ms*/);
        if (r > 0) {
            rxbuf[r] = '\0';
            std::cout << "[<- RX " << r << " bytes] : ";
            std::cout << std::string(rxbuf.data(), r) << "\n";
        } else if (r == 0) {
            std::cout << "[RX timeout]\n";
        } else {
            print_sp_error((enum sp_return)r);
        }
    }

    return 0;
}

int run_full_duplex(struct sp_port *port) {
    std::atomic<bool> running{true};
    std::vector<char> rxbuf(2048);

    // Reader thread: 非阻塞读取并打印
    std::thread reader([&]() {
        while (running) {
            int r = sp_nonblocking_read(port, rxbuf.data(), (int)rxbuf.size()-1);
            if (r > 0) {
                // 打印接收数据（binary-safe）
                std::string s(rxbuf.data(), rxbuf.data() + r);
                std::cout << "[RX " << r << " bytes] -> " << s << std::endl;
            } else if (r < 0) {
                // 出错（可能是不可恢复的）
                print_sp_error((enum sp_return)r);
                // 小睡后继续尝试
                std::this_thread::sleep_for(std::chrono::milliseconds(50));
            } else {
                // r == 0: 没数据，短暂休眠避免忙等
                std::this_thread::sleep_for(std::chrono::milliseconds(30));
            }
        }
    });

    // Writer loop (主线程)：读取 stdin 并非阻塞写
    std::cout << "全双工模式 (非阻塞)：输入文本回车发送。EOF( Ctrl+D/Ctrl+Z ) 退出。\n";
    std::string line;
    while (true) {
        if (!std::getline(std::cin, line)) {
            // EOF -> 停止
            running = false;
            break;
        }
        // 发送数据（可能需要循环以处理部分写）
        const char *buf = line.c_str();
        int remaining = (int)line.size();
        const int WRITE_TIMEOUT_MS = 0; // nonblocking write ignores timeout param, keep 0
        while (remaining > 0) {
            int w = sp_nonblocking_write(port, buf, remaining);
            if (w > 0) {
                remaining -= w;
                buf += w;
            } else if (w == 0) {
                // 没能写入（通常缓冲区满），稍等再重试
                std::this_thread::sleep_for(std::chrono::milliseconds(20));
            } else {
                print_sp_error((enum sp_return)w);
                break;
            }
        }
        // 可选发送换行
        const char *nl = "\r\n";
        sp_nonblocking_write(port, nl, 2);
    }

    // 等待 reader 结束
    if (reader.joinable()) reader.join();
    return 0;
}
int test_serial_main(){
    const char *portname = "COM4"; // 固定 COM1 要求
    const char *mode = "full"; // 默认 full

    struct sp_port *port = nullptr;
    if (sp_get_port_by_name(portname, &port) != SP_OK || port == nullptr) {
        std::cerr << "找不到端口: " << portname << "\n";
        return 1;
    }

    if (sp_open(port, SP_MODE_READ_WRITE) != SP_OK) {
        std::cerr << "打开端口失败: " << portname << "\n";
        print_sp_error(SP_ERR_FAIL);
        sp_free_port(port);
        return 1;
    }

    if (!configure_port(port)) {
        std::cerr << "配置端口失败\n";
        sp_close(port);
        sp_free_port(port);
        return 1;
    }

    std::cout << "Opened " << portname << "\n";

    int rc = 0;
    if (strcmp(mode, "half") == 0) {
        rc = run_half_duplex(port);
    } else {
        rc = run_full_duplex(port);
    }

    sp_flush(port, SP_BUF_BOTH);
    sp_close(port);
    sp_free_port(port);
    return rc;
}